/*
 * @Author: lixu lixu@puchigames.com
 * @Date: 2025-06-16 10:17:13
 * @LastEditors: lixu lixu@puchigames.com
 * @LastEditTime: 2025-06-16 10:17:20
 * @FilePath: /go-helper/utils/struct.go
 * @Description: 结构体处理工具函数，包含结构体转换、字段操作、标签处理等功能
 */
package ixUtils

import (
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
)

// StructToMap 将结构体转换为map
func StructToMap(obj interface{}) (map[string]interface{}, error) {
	if obj == nil {
		return nil, errors.New("object is nil")
	}

	data, err := json.Marshal(obj)
	if err != nil {
		return nil, err
	}

	var result map[string]interface{}
	if err := json.Unmarshal(data, &result); err != nil {
		return nil, err
	}
	return result, nil
}

// MapToStruct 将map转换为结构体
func MapToStruct(data map[string]interface{}, result interface{}) error {
	if data == nil {
		return errors.New("data is nil")
	}
	if result == nil {
		return errors.New("result is nil")
	}

	jsonData, err := json.Marshal(data)
	if err != nil {
		return err
	}
	return json.Unmarshal(jsonData, result)
}

// GetStructFields 获取结构体的所有字段名
func GetStructFields(obj interface{}) []string {
	if obj == nil {
		return nil
	}

	t := reflect.TypeOf(obj)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	if t.Kind() != reflect.Struct {
		return nil
	}

	var fields []string
	for i := 0; i < t.NumField(); i++ {
		fields = append(fields, t.Field(i).Name)
	}
	return fields
}

// GetStructTags 获取结构体指定tag的所有字段值
func GetStructTags(obj interface{}, tagName string) map[string]string {
	if obj == nil {
		return nil
	}
	if tagName == "" {
		return nil
	}

	t := reflect.TypeOf(obj)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	if t.Kind() != reflect.Struct {
		return nil
	}

	tags := make(map[string]string)
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		if tag := field.Tag.Get(tagName); tag != "" {
			tags[field.Name] = tag
		}
	}
	return tags
}

// GetStructFieldValue 获取结构体指定字段的值
func GetStructFieldValue(obj interface{}, fieldName string) (interface{}, error) {
	if obj == nil {
		return nil, errors.New("object is nil")
	}
	if fieldName == "" {
		return nil, errors.New("field name cannot be empty")
	}

	v := reflect.ValueOf(obj)
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}
	if v.Kind() != reflect.Struct {
		return nil, errors.New("not a struct")
	}

	field := v.FieldByName(fieldName)
	if !field.IsValid() {
		return nil, fmt.Errorf("field %s not found", fieldName)
	}
	return field.Interface(), nil
}

// SetStructFieldValue 设置结构体指定字段的值
func SetStructFieldValue(obj interface{}, fieldName string, value interface{}) error {
	if obj == nil {
		return errors.New("object is nil")
	}
	if fieldName == "" {
		return errors.New("field name cannot be empty")
	}

	v := reflect.ValueOf(obj)
	if v.Kind() != reflect.Ptr {
		return errors.New("obj must be a pointer")
	}
	v = v.Elem()
	if v.Kind() != reflect.Struct {
		return errors.New("not a struct")
	}

	field := v.FieldByName(fieldName)
	if !field.IsValid() {
		return fmt.Errorf("field %s not found", fieldName)
	}
	if !field.CanSet() {
		return fmt.Errorf("field %s cannot be set", fieldName)
	}

	val := reflect.ValueOf(value)
	if field.Type() != val.Type() {
		return fmt.Errorf("type mismatch: expected %v, got %v", field.Type(), val.Type())
	}

	field.Set(val)
	return nil
}

// HasStructField 检查结构体是否包含指定字段
func HasStructField(obj interface{}, fieldName string) bool {
	if obj == nil {
		return false
	}
	if fieldName == "" {
		return false
	}

	t := reflect.TypeOf(obj)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	if t.Kind() != reflect.Struct {
		return false
	}

	_, ok := t.FieldByName(fieldName)
	return ok
}

// GetStructFieldType 获取结构体指定字段的类型
func GetStructFieldType(obj interface{}, fieldName string) (reflect.Type, error) {
	if obj == nil {
		return nil, errors.New("object is nil")
	}
	if fieldName == "" {
		return nil, errors.New("field name cannot be empty")
	}

	t := reflect.TypeOf(obj)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	if t.Kind() != reflect.Struct {
		return nil, errors.New("not a struct")
	}

	field, ok := t.FieldByName(fieldName)
	if !ok {
		return nil, fmt.Errorf("field %s not found", fieldName)
	}
	return field.Type, nil
}

// StructToJson 将结构体转换为JSON字符串
func StructToJson(obj interface{}) (string, error) {
	if obj == nil {
		return "", errors.New("object is nil")
	}

	data, err := json.Marshal(obj)
	if err != nil {
		return "", err
	}
	return string(data), nil
}

// JsonToStruct 将JSON字符串转换为结构体
func JsonToStruct(data string, result interface{}) error {
	if data == "" {
		return errors.New("data is empty")
	}
	if result == nil {
		return errors.New("result is nil")
	}

	return json.Unmarshal([]byte(data), result)
}

// CopyStruct 复制结构体（浅拷贝）
func CopyStruct(src, dst interface{}) error {
	if src == nil {
		return errors.New("source is nil")
	}
	if dst == nil {
		return errors.New("destination is nil")
	}

	srcValue := reflect.ValueOf(src)
	dstValue := reflect.ValueOf(dst)

	if srcValue.Kind() != reflect.Ptr || dstValue.Kind() != reflect.Ptr {
		return errors.New("src and dst must be pointers")
	}

	srcValue = srcValue.Elem()
	dstValue = dstValue.Elem()

	if srcValue.Kind() != reflect.Struct || dstValue.Kind() != reflect.Struct {
		return errors.New("src and dst must be struct pointers")
	}

	srcType := srcValue.Type()

	for i := 0; i < srcValue.NumField(); i++ {
		srcField := srcValue.Field(i)
		srcFieldName := srcType.Field(i).Name

		if dstField := dstValue.FieldByName(srcFieldName); dstField.IsValid() && dstField.CanSet() {
			if srcField.Type() == dstField.Type() {
				dstField.Set(srcField)
			}
		}
	}

	return nil
}

// StructToMapWithTag 将结构体转换为map，使用指定的tag作为key
func StructToMapWithTag(obj interface{}, tagName string) (map[string]interface{}, error) {
	if obj == nil {
		return nil, errors.New("object is nil")
	}
	if tagName == "" {
		return nil, errors.New("tag name cannot be empty")
	}

	t := reflect.TypeOf(obj)
	v := reflect.ValueOf(obj)

	if t.Kind() == reflect.Ptr {
		t = t.Elem()
		v = v.Elem()
	}

	if t.Kind() != reflect.Struct {
		return nil, errors.New("not a struct")
	}

	result := make(map[string]interface{})
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		tag := field.Tag.Get(tagName)
		if tag == "" {
			tag = field.Name
		}
		result[tag] = v.Field(i).Interface()
	}

	return result, nil
}

// MapToStructWithTag 将map转换为结构体，使用指定的tag作为key
func MapToStructWithTag(data map[string]interface{}, result interface{}, tagName string) error {
	if data == nil {
		return errors.New("data is nil")
	}
	if result == nil {
		return errors.New("result is nil")
	}
	if tagName == "" {
		return errors.New("tag name cannot be empty")
	}

	t := reflect.TypeOf(result)
	v := reflect.ValueOf(result)

	if t.Kind() != reflect.Ptr {
		return errors.New("result must be a pointer")
	}

	t = t.Elem()
	v = v.Elem()

	if t.Kind() != reflect.Struct {
		return errors.New("result must be a struct pointer")
	}

	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		tag := field.Tag.Get(tagName)
		if tag == "" {
			tag = field.Name
		}

		if value, ok := data[tag]; ok {
			fieldValue := v.Field(i)
			if fieldValue.CanSet() {
				val := reflect.ValueOf(value)
				if fieldValue.Type() == val.Type() {
					fieldValue.Set(val)
				}
			}
		}
	}

	return nil
}

// ========== 强制转换版本（不返回错误） ==========

// MustStructToMap 强制将结构体转换为map
func MustStructToMap(obj interface{}) map[string]interface{} {
	result, _ := StructToMap(obj)
	if result == nil {
		return make(map[string]interface{})
	}
	return result
}

// MustMapToStruct 强制将map转换为结构体
func MustMapToStruct(data map[string]interface{}, result interface{}) {
	MapToStruct(data, result)
}

// MustGetStructFieldValue 强制获取结构体指定字段的值
func MustGetStructFieldValue(obj interface{}, fieldName string) interface{} {
	result, _ := GetStructFieldValue(obj, fieldName)
	return result
}

// MustSetStructFieldValue 强制设置结构体指定字段的值
func MustSetStructFieldValue(obj interface{}, fieldName string, value interface{}) {
	SetStructFieldValue(obj, fieldName, value)
}

// MustGetStructFieldType 强制获取结构体指定字段的类型
func MustGetStructFieldType(obj interface{}, fieldName string) reflect.Type {
	result, _ := GetStructFieldType(obj, fieldName)
	return result
}

// MustStructToJson 强制将结构体转换为JSON字符串
func MustStructToJson(obj interface{}) string {
	result, _ := StructToJson(obj)
	return result
}

// MustJsonToStruct 强制将JSON字符串转换为结构体
func MustJsonToStruct(data string, result interface{}) {
	JsonToStruct(data, result)
}

// MustCopyStruct 强制复制结构体
func MustCopyStruct(src, dst interface{}) {
	CopyStruct(src, dst)
}

// MustStructToMapWithTag 强制将结构体转换为map，使用指定的tag作为key
func MustStructToMapWithTag(obj interface{}, tagName string) map[string]interface{} {
	result, _ := StructToMapWithTag(obj, tagName)
	if result == nil {
		return make(map[string]interface{})
	}
	return result
}

// MustMapToStructWithTag 强制将map转换为结构体，使用指定的tag作为key
func MustMapToStructWithTag(data map[string]interface{}, result interface{}, tagName string) {
	MapToStructWithTag(data, result, tagName)
}
